#include "wiki_manager_widget.h"
#include "ui_wiki_manager_widget.h"
#include "add_wiki_dialog.h"
#include "wiki_info_table.h"
#include "wiki_data_table.h"
#include "sqlite_manager.h"
#include "easylogging++.h"
#include <QUuid>

WikiManagerWidget::WikiManagerWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::WikiManagerWidget),
    m_wikiTreeWidgetItemMenu(nullptr),
    m_currentMenuAtItem(nullptr)
{
    ui->setupUi(this);
    initUi();
    initEvents();
    initMenu();
    initWikiInfo();
}

WikiManagerWidget::~WikiManagerWidget()
{
    delete ui;
}

void WikiManagerWidget::initUi()
{
    ui->wikiTreeWidget->setDragEnabled(true);
    ui->wikiTreeWidget->setAcceptDrops(true);
    ui->wikiTreeWidget->setDropIndicatorShown(true);
    ui->wikiTreeWidget->setDragDropMode(QAbstractItemView::InternalMove);
}

void WikiManagerWidget::initEvents()
{
    /** wiki树节点移动信号 */
    connect(ui->wikiTreeWidget, &TreeWidget::itemIsMoved, this, &WikiManagerWidget::onWikiItemIsMoved);
    /** 添加wiki按钮单击信号 */
    connect(ui->addWikiBtn, &QPushButton::clicked, this, &WikiManagerWidget::onAddWikiBtnClicked);
    /** wiki树当前节点改变信号 */
    connect(ui->wikiTreeWidget, &QTreeWidget::currentItemChanged, this, &WikiManagerWidget::onCurrentWikiChanged);
    /** wiki节点鼠标按下信号 */
    connect(ui->wikiTreeWidget, &QTreeWidget::itemPressed, this, &WikiManagerWidget::onWikiIsPressed);
    /** wiki节点内容改变信号 */
    connect(ui->wikiTreeWidget, &QTreeWidget::itemChanged, this, &WikiManagerWidget::onWikiNameChanged);
    /** 保存文档按钮单击信号 */
    connect(ui->docEditWidget, &DocEditWidget::saveDocTriggered, this, &WikiManagerWidget::onSaveWikiBtnClicked);
}

void WikiManagerWidget::initWikiInfo()
{
    WikiInfoTable wit;
    QList<QVariantList> data;
    bool selectStatus = wit.selectAll({
                                          "uuid", "wiki_name", "parent_wiki_uuid"
                                      },
                                      data);
    if (!selectStatus)
    {
        LOG(ERROR) << "select wiki info failed!";
        return ;
    }

    QHash<QString, QTreeWidgetItem*> itemMap;
    for (int i = 0; i < data.count(); i++)
    {
        QString parentTaskUuid = data[i][2].toString();
        QString uuid = data[i][0].toString();
        QTreeWidgetItem* newItem = nullptr;
        /** 如果已经创建wiki节点，则设置节点文本内容 */
        if (itemMap.find(uuid) != itemMap.end())
        {
            newItem = itemMap[uuid];
            newItem->setText(0, data[i][1].toString());
        }
        else    /** 如果未创建wiki节点，则创建 */
        {
            newItem = new QTreeWidgetItem({data[i][1].toString()});
            newItem->setData(0, Qt::UserRole, uuid);
            newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
        }

        itemMap[uuid] = newItem;

        if (0 == parentTaskUuid.size())
        {
            ui->wikiTreeWidget->addTopLevelItem(newItem);
        }
        else if (itemMap.find(parentTaskUuid) != itemMap.end())
        {
            QTreeWidgetItem* parentItem = itemMap[parentTaskUuid];
            parentItem->addChild(newItem);
        }
        else
        {
            QTreeWidgetItem* parentItem = new QTreeWidgetItem();
            parentItem->setData(0, Qt::UserRole, parentTaskUuid);
            parentItem->addChild(newItem);
            parentItem->setFlags(parentItem->flags() | Qt::ItemIsEditable);
            itemMap[parentTaskUuid] = parentItem;
        }
    }
}

void WikiManagerWidget::initMenu()
{
    if (!m_wikiTreeWidgetItemMenu)
    {
        m_wikiTreeWidgetItemMenu = new QMenu(this);
        QAction *newChildWikiAction = new QAction(QStringLiteral("新建子文档"));
        QAction *renameWikiAction = new QAction(QStringLiteral("重命名"));
        QAction *deleteWikiAction = new QAction(QStringLiteral("删除文档"));
        QAction *deleteChildWikiAction = new QAction(QStringLiteral("删除子文档"));

        m_wikiTreeWidgetItemMenu->addAction(newChildWikiAction);
        m_wikiTreeWidgetItemMenu->addAction(renameWikiAction);
        m_wikiTreeWidgetItemMenu->addAction(deleteWikiAction);
        m_wikiTreeWidgetItemMenu->addAction(deleteChildWikiAction);

        connect(newChildWikiAction, &QAction::triggered, this, [=]() {
            if (!m_currentMenuAtItem) {
                return ;
            }

            addWiki(m_currentMenuAtItem);
            m_currentMenuAtItem = nullptr;
        });
        connect(renameWikiAction, &QAction::triggered,
                this, &WikiManagerWidget::renameWiki);
        connect(deleteWikiAction, &QAction::triggered,
                this, &WikiManagerWidget::onDeleteWikiTriggered);
        connect(deleteChildWikiAction, &QAction::triggered,
                this, &WikiManagerWidget::onDeleteChildWikiTriggered);
    }
}

void WikiManagerWidget::onAddWikiBtnClicked()
{
    addWiki();
}

void WikiManagerWidget::onCurrentWikiChanged(QTreeWidgetItem *currentItem, QTreeWidgetItem *previousItem)
{
    Q_UNUSED(previousItem)
    m_currentWikiUuid = currentItem->data(0, Qt::UserRole).toString();
    WikiDataTable wdt;
    QString wiki_data;
    wdt.selectWikiDataByUuid(m_currentWikiUuid, wiki_data);
    ui->docEditWidget->setDoc(wiki_data);
}

void WikiManagerWidget::onWikiIsPressed(QTreeWidgetItem *item, int column)
{
    Q_UNUSED(column)
    m_currentMenuAtItem = item;
    /** 鼠标右键，弹出菜单 */
    if (qApp->mouseButtons() == Qt::RightButton)
    {
        m_wikiTreeWidgetItemMenu->exec(QCursor::pos());
    }
}

void WikiManagerWidget::onWikiNameChanged(QTreeWidgetItem *item, int column)
{
    Q_UNUSED(column)
    WikiInfoTable wit;
    wit.updateWikiName(item->data(0, Qt::UserRole).toString(),
                       item->text(0));
}

void WikiManagerWidget::onSaveWikiBtnClicked()
{
    WikiDataTable wdt;
    wdt.updateWikiData(m_currentWikiUuid, ui->docEditWidget->getDoc());
}

void WikiManagerWidget::onDeleteWikiTriggered()
{
    if (nullptr == m_currentMenuAtItem)
    {
        return ;
    }
    deleteWiki(m_currentMenuAtItem);
    m_currentMenuAtItem = nullptr;
}

void WikiManagerWidget::onDeleteChildWikiTriggered()
{
    if (nullptr == m_currentMenuAtItem)
    {
        return ;
    }

    for (int i = m_currentMenuAtItem->childCount() - 1; i >= 0; i--)
    {
        deleteWiki(m_currentMenuAtItem->child(i));
    }

    m_currentMenuAtItem = nullptr;
}

void WikiManagerWidget::onWikiItemIsMoved(QTreeWidgetItem *item)
{
    QTreeWidgetItem *parent     = item->parent();
    QString          parentUuid = "";
    if (nullptr != parent) {
        parentUuid = item->parent()->data(0, Qt::UserRole).toString();
    }

    WikiInfoTable wit;
    wit.updateWikiParentUuid(item->data(0, Qt::UserRole).toString(), parentUuid);
}

void WikiManagerWidget::renameWiki()
{
    if (nullptr == m_currentMenuAtItem)
    {
        return ;
    }

    ui->wikiTreeWidget->editItem(m_currentMenuAtItem, 0);
}

void WikiManagerWidget::addWiki(QTreeWidgetItem* parentItem)
{
    AddWikiDialog awd;
    awd.setWindowTitle(QStringLiteral("添加wiki"));
    int ret = awd.exec();
    if (QDialog::Accepted == ret) {
        QString parentUuid = "";
        if (parentItem) {
            parentUuid = parentItem->data(0, Qt::UserRole).toString();
        }
        QString wikiName = awd.getWikiName();
        QString uuid = QUuid::createUuid().toString(QUuid::WithoutBraces);
        WikiInfoTable wit;
        SqliteManager sm;
        bool isTransactionStart = sm.transactionStart();
        if (!isTransactionStart) {
            LOG(ERROR) << "transaction start failed!";
            return ;
        }
        bool insertWikiStatus = wit.insertWikiInTransiction(uuid, wikiName, parentUuid, sm);
        if (!insertWikiStatus) {
            sm.rollback();
            sm.transactionEnd();
            LOG(ERROR) << "insert wiki info failed!";
            return ;
        }

        WikiDataTable wdt;
        bool insertWikiDataStatus = wdt.insertWikiDataInTransaction(uuid, "", sm);
        if (!insertWikiDataStatus) {
            sm.rollback();
            sm.transactionEnd();
            LOG(ERROR) << "insert wiki data failed!";
            return ;
        }

        sm.transactionEnd();

        QTreeWidgetItem *item = new QTreeWidgetItem({wikiName});
        item->setData(0, Qt::UserRole, uuid);
        item->setFlags(item->flags() | Qt::ItemIsEditable);

        if (parentItem)
        {
            parentItem->addChild(item);
        }
        else
        {
            ui->wikiTreeWidget->addTopLevelItem(item);
        }
    }
}

void WikiManagerWidget::deleteWiki(QTreeWidgetItem *item)
{
    if (!item) {
        return ;
    }

    for (int i = item->childCount() - 1; i >= 0; i--)
    {
        deleteWiki(item->child(i));
    }

    SqliteManager sm;
    bool transactionStatus = sm.transactionStart();
    if (!transactionStatus)
    {
        LOG(ERROR) << "transaction start failed!";
        return ;
    }
    QString uuid = item->data(0, Qt::UserRole).toString();
    WikiInfoTable wit;
    wit.deleteWikiByUuidInTransaction(uuid, sm);
    WikiDataTable wdt;
    wdt.deleteWikiDataByUuidInTransaction(uuid, sm);

    QTreeWidgetItem *parent = item->parent();
    if (nullptr != parent)
    {
        parent->takeChild(parent->indexOfChild(item));
    }
    else
    {
        ui->wikiTreeWidget->takeTopLevelItem(ui->wikiTreeWidget->indexOfTopLevelItem(item));
    }
}
